<script lang="ts" setup>
import { _require } from "@@/utils/tools";
import useBalanceStore, { StoreCoinItem } from "@@/store/useBalanceStore";
import { toast } from "@@/hooks/vantHooks";
import {
  fixedDecimals,
  foldDecimal,
  normalNumber,
} from "@@/utils/tools/format";
import { useRpopupPickerRef } from "@@/components/rework/RpopupPicker";
import { sdkSwap } from "@@/sdk/web3Eth";
import { apiSwapTxid } from "@@/api/transaction/submitTxid";
import { sysLoad } from "@@/hooks/sysHooks";
import { multiply, divide, subtract, add } from "mathjs";
import useUserinfoStore from "@@/store/useUserinfoStore";
import { contrastAddress } from "@@/utils/tools/is";
import { LpCoin, WkLpInfo } from "../wkLoopInfo";
const props = defineProps<{
  lpCoinEnum: AnyObject<LpCoin>;
  getWkLpInfo: () => Promise<WkLpInfo | undefined>;
}>();

const userinfoStore = useUserinfoStore();
const { userinfo } = storeToRefs(userinfoStore);

const { t } = useI18n();
const balanceStore = useBalanceStore();
const { ethCoinEnum } = storeToRefs(balanceStore);

/**当前选中发送币种 */
const fromCoin = computed(
  () => ethCoinEnum.value[RpickerFromRef.value?.elect?.id!]
);
const currentFromCoinApprove = computed(() =>
  balanceStore.checkApprove(fromCoin.value, Number(formData.amount))
);

/**当前选中接收币种 */
const toCoin = computed(
  () => ethCoinEnum.value[RpickerToRef.value?.elect?.id!]
);
const LpToCoin = computed(() => props.lpCoinEnum[toCoin.value?.id!]);
const LpFromCoin = computed(() => props.lpCoinEnum[fromCoin.value?.id!]);
const RpickerFromRef = useRpopupPickerRef<StoreCoinItem>();
const RpickerToRef = useRpopupPickerRef<StoreCoinItem>();

/**picker选择器数据 */
const pickerData = computed<StoreCoinItem[]>(() =>
  Object.values(ethCoinEnum.value)
);
/**选择器接收币种数据 */
const RpickerToData = computed<StoreCoinItem[]>(() =>
  pickerData.value.filter((v) => v.id !== RpickerFromRef.value?.electValue)
);
/**选择器发送币种数据 */
const RpickerFromData = computed<StoreCoinItem[]>(() =>
  pickerData.value.filter((v) => v.id !== RpickerToRef.value?.electValue)
);

const formData = reactive({
  amount: "",
  toAmount: "",
});
let lastInput = inputFromAmount;
function inputFromAmount() {
  evaluationSwapTo();
  lastInput = inputFromAmount;
}
function inputToAmount() {
  evaluationSwapFrom();
  lastInput = inputToAmount;
}
function swipeFromTo() {
  if (!RpickerFromRef.value || !RpickerToRef.value) return;
  [RpickerFromRef.value.electValue, RpickerToRef.value.electValue] = [
    RpickerToRef.value.electValue,
    RpickerFromRef.value.electValue,
  ];
  inputFromAmount();
}
watch(
  () => props.lpCoinEnum,
  () => lastInput(),
  { deep: true }
);

const defaultServicePrice = 0.01;
/**服务费 */
let servicePrice = ref(defaultServicePrice);
/**
 * * 计算服务费
 * @param original 原数据
 * @param reverse 逆转计算，得到原价
 */
function serviceCharge(original: number, reverse = false) {
  if (reverse === true)
    return divide(original, subtract(1, servicePrice.value));
  return multiply(original, subtract(1, servicePrice.value));
}
const $servicePrice = computed(() => {
  const toAmount = Number(formData.toAmount);
  const amount = Number(formData.amount);
  if (!(toAmount > 0) || !(amount > 0)) return 0;
  return multiply(Number(formData.toAmount), servicePrice.value);
});

/**计算输入框数据 */
function evaluationSwapTo() {
  if (!LpToCoin.value) return;
  const toCoinTotal = Number(LpToCoin.value.totalAmount);
  const amount = Number(formData.amount);
  if (!amount) return (formData.toAmount = "");
  if (!estimateTotal.value) return;
  //输入to = 总to - 预估总to
  //预估总to = (总from * 总to) / (总from + (输入from * 服务费))
  const toAmount = subtract(toCoinTotal, estimateTotal.value.to);
  if (!(toAmount > 0)) return (formData.toAmount = "0");
  formData.toAmount = normalNumber(toAmount);
}

/**计算输入框数据 */
function evaluationSwapFrom() {
  if (!LpToCoin.value || !LpFromCoin.value) return;
  const toCoinTotal = Number(LpToCoin.value.totalAmount);
  const fromCoinTotal = Number(LpFromCoin.value.totalAmount);
  const toAmount = Number(formData.toAmount);
  if (!toAmount) formData.amount = "";
  //输入to = 总to - (总from * 总to) / (总from + (输入from * 服务费))
  //输入from = ((总from * 总to) / (总to - (输入to)) - 总from) / 服务费
  const amount = serviceCharge(
    subtract(
      divide(
        multiply(fromCoinTotal, toCoinTotal),
        subtract(toCoinTotal, toAmount)
      ),
      fromCoinTotal
    ),
    true
  );
  if (!(amount > 0)) return (formData.amount = "0");
  formData.amount = normalNumber(amount);
}
/**初始价格 */
const originalPrice = computed(() => {
  if (!LpToCoin.value || !LpFromCoin.value) return;
  const toCoinTotal = Number(LpToCoin.value.totalAmount);
  const fromCoinTotal = Number(LpFromCoin.value.totalAmount);
  return divide(fromCoinTotal, toCoinTotal);
});
/**现在价格 */
const price = computed(() => {
  if (!estimateTotal.value) return;
  const { from, to } = estimateTotal.value;
  return divide(from, to);
});
/**预估总量 */
const estimateTotal = computed(() => {
  if (!LpToCoin.value || !LpFromCoin.value) return;
  const toCoinTotal = Number(LpToCoin.value.totalAmount);
  const fromCoinTotal = Number(LpFromCoin.value.totalAmount);
  //预估总to = (总from * 总to) / (总from + (输入from * 服务费))
  const fromAmount = serviceCharge(Number(formData.amount));
  /**预估from总 */
  const from = add(fromCoinTotal, fromAmount);
  /**预估to总 */
  const to = divide(multiply(fromCoinTotal, toCoinTotal), from);
  return {
    from,
    to,
  };
});
/**滑点 */
const slide = computed(() => {
  if (!LpToCoin.value) return 0;
  const toCoinTotal = Number(LpToCoin.value.totalAmount);
  if (!estimateTotal.value) return 0;
  const { to } = estimateTotal.value;
  const toAmount = Number(formData.toAmount);
  const amount = Number(formData.amount);
  if (!(toAmount > 0) || !(amount > 0)) return 0;
  return subtract(1, divide(to, toCoinTotal));
});

sysLoad(loadPageData);
/**更新from币种数据数据 */
function updateFromCoin() {
  balanceStore.findBalance(fromCoin.value!);
  balanceStore.findApprove(fromCoin.value, balanceStore.approveAddresss);
}

onMounted(() => {
  watch(
    () => RpickerFromRef.value?.elect?.id,
    (newValue, oldValue) => {
      if (newValue === oldValue) return;
      updateFromCoin();
    },
    {
      deep: true,
      immediate: true,
    }
  );
  watch(
    () => [RpickerFromRef.value?.elect?.id, RpickerToRef.value?.elect?.id],
    (newValue, oldValue) => {
      if (newValue[0] === oldValue[0] && newValue[1] === oldValue[1]) return;
      if (fromCoin.value?.code.toUpperCase() === "WKC") servicePrice.value = 0;
      else servicePrice.value = defaultServicePrice;
    },
    {
      deep: true,
    }
  );
});

/**按钮加载状态 */
const btnLoading = reactive({
  submitBtn: false,
  approveBtn: false,
});
async function submitBtn() {
  const amount = Number(formData.amount);
  const toAmount = Number(formData.toAmount);
  const to_Coin = toCoin.value!;
  const from_coin = fromCoin.value!;
  const ratio = userinfo.value?.set.slip_point;
  if (!ratio) return toast.text(t("shu-ju-yi-chang-qing-chong-shi"));
  const mini = 0;
  if (!(amount > mini))
    return toast.text(`${t("fa-song-shu-liang-bu-neng-xiao-yu")} ${mini}`);
  btnLoading.submitBtn = true;
  const balance = await balanceStore.findBalance(from_coin);
  btnLoading.submitBtn = false;
  if (!(amount <= Number(balance))) return toast.text(t("yu-e-bu-zu"));
  btnLoading.submitBtn = true;
  await swap(amount, toAmount, from_coin, to_Coin, ratio);
  btnLoading.submitBtn = false;
}
/**usdt合约 */
const usdtContract_addr = computed(
  () => balanceStore.getCoinByCode("usdt")?.contract_addr
);
/**wkc合约 */
const wkcContract_addr = computed(
  () => balanceStore.getCoinByCode("wkc")?.contract_addr
);
/**发起兑换 */
async function swap(
  amount: number,
  toAmount: number,
  fromCoin: CoinPay,
  toCoin: CoinPay,
  ratio: number
) {
  let toMini = 0;
  if (contrastAddress(fromCoin.contract_addr, usdtContract_addr.value))
    toMini = toAmount * (1 - ratio / 100);
  // if (fromCoin.contract_addr?.toLowerCase() === wkcContract_addr)
  //   toMini = toAmount * (1 - ratio / 100);
  const res = await sdkSwap(
    amount,
    fromCoin.format,
    [fromCoin.contract_addr!, toCoin.contract_addr!],
    balanceStore.approveAddresss,
    toMini,
    toCoin.format
  );
  if (!res.status) return toast.error(res.message || "fail");
  await apiSwapTxid({
    txid: res.data!,
    number: amount,
    from_id: fromCoin.id,
    to_id: toCoin.id,
  });
  setTimeout(updateFromCoin, 10 * 1000);
}
async function approveBtn() {
  btnLoading.approveBtn = true;
  await balanceStore.approve(
    fromCoin.value,
    undefined,
    balanceStore.approveAddresss
  );
  btnLoading.approveBtn = false;
}

/**加载页面数据 */
function loadPageData() {
  updateFromCoin();
}

/**兑换按钮状态 */
const submitBtnState = computed(() => {
  if (!slide.value) return;
  const slip_point = Number(userinfo.value?.set.slip_point);
  const slide100 = slide.value * 100;
  const disabled = !(slide100 <= slip_point);
  if (disabled)
    return {
      disabled,
      message: t("jia-ge-ying-xiang-guo-gao"),
    };
  return {
    disabled,
    message: t("dui-huan"),
  };
});
const radioBtns = computed(() => [
  {
    text: "25%",
    value: multiply(Number(fromCoin.value?.balance || 0), 0.25).toString(),
  },
  {
    text: "50%",
    value: multiply(Number(fromCoin.value?.balance || 0), 0.5).toString(),
  },
  {
    text: "75%",
    value: multiply(Number(fromCoin.value?.balance || 0), 0.75).toString(),
  },
  {
    text: "MAX",
    value: fromCoin.value?.balance || "0",
  },
]);
</script>

<template>
  <div class="auto-MT-md">
    <Ccard class="PB-xxl">
      <div class="auto-MT-md">
        <div class="flex-A-C auto-ML-xs">
          <RpopupPicker
            class="flex-A-C"
            valueKey="id"
            ref="RpickerFromRef"
            :picker-data="RpickerFromData"
            :default-elect="balanceStore.getCoinByCode('usdt')?.id"
          >
            <template #left-content>
              <Rimage size="42rem" :src="RpickerFromRef?.elect?.logo" />
              <div class="ML-xs">{{ RpickerFromRef?.elect?.code }}</div>
            </template>
            <template #option="{ code, logo }: StoreCoinItem">
              <div class="flex-A-C flex-J-SB" style="width: 5em">
                <Rimage size="42rem" :src="logo" />
                <div class="T-A-C" style="width: 3em">{{ code }}</div>
              </div>
            </template>
          </RpopupPicker>
        </div>
        <Rinput
          label-align="top"
          class="T-S-xxl"
          type="number"
          v-model="formData.amount"
          @input="inputFromAmount"
          :border-mode="'bottom'"
          :placeholder="$t('qing-shu-ru-fa-song-shu-liang')"
        >
          <template #right-icon>
            <div class="T-S-sm">
              <span>{{ $t("yue") }} </span>
              <span>{{ fixedDecimals(fromCoin?.balance, 4) }}</span>
            </div>
          </template>
        </Rinput>
        <RradioBtnGroup v-model="formData.amount" @change="inputFromAmount()">
          <RradioBtn :value="item.value" v-for="item in radioBtns">
            {{ item.text }}
          </RradioBtn>
        </RradioBtnGroup>
      </div>
    </Ccard>
    <div class="swapBtn">
      <Cicon
        class="active Cicon"
        @click="swipeFromTo"
        name="icon-shangxiaqiehuan"
      />
    </div>
    <!-- 接收币种 -->
    <Ccard class="PT-xxl MT-0">
      <div class="auto-MT-md">
        <div class="flex-A-C">
          <RpopupPicker
            class="flex-A-C"
            valueKey="id"
            ref="RpickerToRef"
            :picker-data="RpickerToData"
            :default-value="balanceStore.getCoinByCode('wkc')?.id"
          >
            <template #left-content>
              <Rimage size="42rem" :src="RpickerToRef?.elect?.logo" />
              <div class="ML-xs">{{ RpickerToRef?.elect?.code }}</div>
            </template>
            <template #option="{ code, logo }: StoreCoinItem">
              <div class="flex-A-C flex-J-SB" style="width: 5em">
                <Rimage size="42rem" :src="logo" />
                <div class="T-A-C" style="width: 3em">{{ code }}</div>
              </div>
            </template>
          </RpopupPicker>
        </div>
        <Rinput
          class="T-S-xxl"
          @input="inputToAmount"
          label-align="top"
          type="number"
          v-model="formData.toAmount"
          :border-mode="'bottom'"
          :placeholder="'0.00'"
        >
          <template #button>
            <div class="T-S-sm">{{ toCoin?.code }}</div>
          </template>
        </Rinput>
        <Ccard class="T-S-sm PT-xs PB-xs" bg="var(--C-B3)" border-style="none">
          <Ccell border-mode="bottom">
            <div>{{ $t("jia-ge") }}</div>

            <template #right>
              <div>
                <span>1</span>
                <span>{{ toCoin?.code }}</span>
                <span> = </span>
                <span>{{ fixedDecimals(price, 6) }}</span>
                <span>{{ fromCoin?.code }}</span>
              </div>
            </template>
          </Ccell>

          <Ccell border-mode="bottom">
            <div>{{ $t("jia-ge-ying-xiang") }}</div>

            <template #right>
              <div>
                <span>{{ fixedDecimals(slide * 100) }}</span>
                <span>%</span>
              </div>
            </template>
          </Ccell>
          <Ccell border-mode="bottom" border-style="none">
            <div>{{ $t("hua-dian") }}</div>

            <template #right>
              <div>
                <span>
                  {{ fixedDecimals($servicePrice) }}
                </span>
                <span>{{ toCoin?.code }}</span>
              </div>
            </template>
          </Ccell>
        </Ccard>
      </div>
    </Ccard>

    <transition name="page">
      <Rbutton
        v-if="!price"
        class="MT-md"
        bg="var(--C-LG1)"
        borderStyle="none"
        :size="'large'"
        disabled
        block
      >
        {{ $t("liu-dong-xing-bu-zu") }}
      </Rbutton>
      <Rbutton
        v-else-if="!currentFromCoinApprove"
        class="MT-md"
        @click="approveBtn"
        :loading="btnLoading.approveBtn"
        bg="var(--C-LG1)"
        borderStyle="none"
        :size="'large'"
        block
      >
        <span>{{ $t("pi-zhun") }}</span>
        <span> {{ fromCoin?.code }}</span>
      </Rbutton>
      <!-- 兑换按钮 -->
      <Rbutton
        v-else
        class="MT-md"
        @click="submitBtn"
        :loading="btnLoading.submitBtn"
        bg="var(--C-LG1)"
        borderStyle="none"
        :size="'large'"
        block
        :disabled="submitBtnState?.disabled"
      >
        {{ submitBtnState?.message }}
      </Rbutton>
    </transition>
    <!-- <div class="flex-J-SB T-S-sm">
        <div @click="$router.push({ name: 'swap-liquidityList' })" class="active">
          {{ $t("liu-dong-xing-lie-biao") }}
        </div>
        <div @click="$router.push({ name: 'swapLogs' })" class="active">
          {{ $t("dui-huan-ji-lu") }}
        </div>
      </div> -->
    <Ccard bg="var(--C-B3)" class="totalView C-white1">
      <div class="T-A-C T-S-sm">
        {{ $t("liu-dong-xing-chi-zi-zong-liang") }}
      </div>
      <CgridCell class="MT-md T-S-sm" :border="false" :separate="'col'">
        <CgcRow>
          <CgcCol> {{ LpFromCoin?.code }}</CgcCol>
          <CgcCol>{{ LpToCoin?.code }} </CgcCol>
        </CgcRow>
        <CgcRow>
          <CgcCol> {{ foldDecimal(LpFromCoin?.totalAmount) }}</CgcCol>
          <CgcCol> {{ foldDecimal(LpToCoin?.totalAmount) }}</CgcCol>
        </CgcRow>
      </CgridCell>
    </Ccard>
  </div>
</template>

<style lang="scss" scoped>
.CgcCol {
  padding-bottom: var(--gap-xs);
}
.swapBtn {
  $offset: -24rem;
  margin-top: $offset;
  margin-bottom: $offset;
  text-align: center;
  .Cicon {
    padding: var(--gap-sm);
    border-radius: 9999rem;
    background-color: var(--C-B1);
    border: solid 1rem var(--C-T1-O1);
    font-size: 26rem;
  }
}
</style>
